#!/usr/bin/env python

#
# OpenLookup - client.py
#
# Copyright 2009 Helsinki Institute for Information Technology
# and the authors.
#
# Authors: Ken Rimey <rimey@hiit.fi>
#

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import sys
from urlparse import urljoin

from openlookup.client.singleton import Proxy
from openlookup.client.keychain import KeyChain, NotFound, Ambiguous

URL = None
#URL = 'http://localhost:5851/'

BROWSER_URL = 'http://any.openlookup.net:5851/'

class Error(Exception): pass

class Client(Proxy):
    def __init__(self, url=None):
        Proxy.__init__(self, url)
        self.browser_url = url or BROWSER_URL

    def get(self, label, principal=None):
        if principal is not None and len(principal) < 40:
            items = self.query_items(label, principal, maxvals=2)
            if len(items) == 0:
                raise Error('Not found.')
            elif len(items) == 1:
                item = items[0]
                principal = item.principal
            else:
                raise Error('Multiple choices.')

        value = Proxy.get(self, label, principal)
        if value is None:
            raise Error('Not found.')
        else:
            self.show_url(label, principal)
            sys.stdout.write(value)

    def put(self, label, principal=None):
        identity = self.get_identity(principal)
        self.show_url(label, identity)
        value = sys.stdin.read()
        Proxy.put(self, label, value, identity)

    def rm(self, label, principal=None):
        identity = self.get_identity(principal)
        self.show_url(label, identity)
        Proxy.rm(self, label, identity)

    def get_identity(self, principal=None):
        if principal is None:
            return None

        keychain = KeyChain()
        try:
            return keychain.find(principal)
        except NotFound:
            raise Error('Private key not found.')
        except Ambiguous:
            raise Error('Multiple choices for private key.')

    def show_url(self, label, principal):
        principal = principal or '-'
        if not isinstance(principal, str):
            principal = principal.hexdigest()

        path = '/value/%s/%s' % (principal, label)
        print >> sys.stderr, '[%s]' % urljoin(self.browser_url, path)

def main(cmd, label, principal=''):
    if cmd not in ('get', 'put', 'rm'):
        usage()

    if principal == '-':
        principal = None
    elif not all(c in '0123456789abcdef' for c in principal):
        usage()

    client = Client(URL)
    try:
        getattr(client, cmd)(label, principal)
    except Error, e:
        sys.exit('Error: %s' % str(e))

def usage():
    msg = 'Usage: %s [get|put|rm] <label> [-|<hexdigit>+]' % sys.argv[0]
    print >> sys.stderr, msg
    sys.exit(2)

if __name__ == '__main__':
    if len(sys.argv) not in (3, 4):
        usage()

    main(*sys.argv[1:])
